/*
 * Clase con funciones para emitir instrucciones en Codigo P.
 * 
 * Basado en el proyecto descrito en: 
 * Louden, K. (1997). Compiler Construction: Principles and Practice. Boston: PWS.
 * 
 * @ Project: Compiler
 * @ File Name: Emit.java
 * @ Date: 21/09/2008
 */
package cml.coding;

import cml.Type;

public class Emit {
	
	public static final int END_OPR = 0;
	public static final int RET_OPR = 1;
	public static final int GT_OPR = 2;
	public static final int LT_OPR = 3;
	public static final int NEQ_OPR = 4;
	public static final int EQ_OPR = 5;
	public static final int GTEQ_OPR = 6;
	public static final int LTEQ_OPR = 7;
	public static final int ADD_OPR = 8;
	public static final int SUB_OPR = 9;
	public static final int MUL_OPR = 10;
	public static final int DIV_OPR = 11;
	public static final int RDI_OPR = 12;
	public static final int WRI_OPR = 13;
	public static final char SEPARATOR = '@';
	
	private static int emitLoc = 1;
	
	/*
	 * Regresa la instruccion de llamada a funcion sin una direccion especifica.
	 * 
	 * @param	func	nombre de la funcion a llamar
	 * @return	llamada a funcion
	 */
	public static String cal(String func) {
		
		return emitLoc++ + ": cal " + func;
	}
	
	/*
	 * Regresa la instruccion de llamada a funcion con una direccion especifica.
	 * 
	 * @param	func	nombre de la funcion a llamar
	 * @param	add		direccion de la llamada
	 * @return	llamada a funcion
	 */
	public static String cal(String func, int add) {
		
		return emitLoc++ + ": cal " + func + ", " + add;
	}
	
	/*
	 * Agrega la direccion a la llamada a funcion.
	 * 
	 * @param	cal	instruccion de llamada a funcion
	 * @param	add		direccion de la llamada	
	 * @return	llamada a funcion con direccion
	 */
	public static String updateCal(String cal, int add) {
		
		cal += ", " + add;
		
		return cal;
	}
	
	/*
	 * Regresa un comentario.
	 * 
	 * @param	c	contenido del comentario
	 * @return	comentario
	 */
	public static String comment(String c) {
		
		return ";" + c;
	}
	
	/*
	 * Regresa la declaracion de una funcion.
	 * 
	 * @param	name	nombre de la funcion
	 * @param	type	tipo de regreso de la funcion
	 * @param	loc		ubicacion de la funcion en el codigo
	 * @return	declaracion de funcion
	 */
	public static String func(String name, String type, int loc) {
		
		return name + ", " + type + ", G, " + loc + " #";
	}
	
	/*
	 * Regresa la instruccion para un salto condicional.
	 * 
	 * @param	cond	condicion
	 * @param	add		direccion
	 * @return	salto condicional
	 */
	public static String jmc(boolean cond, int add) {
		
		return jmc(cond, add + "");
	}
	
	/*
	 * Regresa la instruccion para un salto condicional.
	 * 
	 * @param	cond	condicion
	 * @param	add		direccion
	 * @return	salto condicional
	 */
	public static String jmc(boolean cond, String add) {
		
		if(cond)
			return emitLoc++ + ": jmc v, " + add;
		else return emitLoc++ + ": jmc f, " + add;
	}
	
	/*
	 * Regresa la instruccion para un salto no condicional.
	 * 
	 * @param	add		direccion
	 * @return	salto no condicional
	 */
	public static String jmp(String add) {
		
		return emitLoc++ + ": jmp 0," + add;
	}
	
	/*
	 * Regresa la declaracion de una etiqueta.
	 * 
	 * @param	name	nombre
	 * @param	loc		ubicacion de la etiqueta en el codigo
	 * @return	declaracion de una etiqueta
	 */
	public static String label(String name, int loc) {
		
		return name + ", I, I, " + loc + " #";
	}
	
	/*
	 * Regresa la instruccion para cargar una constante.
	 * 
	 * @param	value	valor de la constante
	 * @return	instruccion cargar una constante
	 */
	public static String lit(boolean value) {
		
		return emitLoc++ + ": lit " + value + ", 0";
	}
	
	/*
	 * Regresa la instruccion para cargar una constante.
	 * 
	 * @param	value	valor de la constante
	 * @return	instruccion cargar una constante
	 */
	public static String lit(double value) {
		
		return emitLoc++ + ": lit " + value + ", 0";
	}
	
	/*
	 * Regresa la instruccion para cargar una constante.
	 * 
	 * @param	value	valor de la constante
	 * @return	instruccion cargar una constante
	 */
	public static String lit(int value) {
		
		return emitLoc++ + ": lit " + value + ", 0";
	}
	
	/*
	 * Regresa la instruccion para cargar una constante.
	 * 
	 * @param	value	valor de la constante
	 * @return	instruccion cargar una constante
	 */
	public static String lit(String value) {
		
		return emitLoc++ + ": lit \"" + value + "\", 0";
	}
	
	/*
	 * Regresa la instruccion para cargar una variable.
	 * 
	 * @param	add	direccion de la variable
	 * @return	instruccion cargar una variable
	 */
	public static String lod(String add) {
		
		return emitLoc++ + ": lod " + add + ", 0";
	}
	
	/*
	 * Regresa la instruccion para realizar una operacion especial.
	 * 
	 * @param	code	codigo de la operacion
	 * @return	instruccion de operacion especial
	 */
	public static String opr(int code) {
		
		String i = emitLoc++ + ": opr 0, " + code;
		
		if(code == END_OPR)
			emitLoc = 0;
		
		return i;
	}
	
	/*
	 * Regresa la instruccion para guardar un valor en una variable.
	 * 
	 * @param	add	direccion de la variable
	 * @return	instruccion guardar valor de variable
	 */
	public static String sto(String add) {
	
		return emitLoc++ + ": sto 0, " + add;
	}
	
	/*
	 * Regresa la declaracion de una variable.
	 * 
	 * @param	name	nombre de la variable
	 * @param	type	tipo de dato de la variable
	 * @param	scope	bloque de la variable
	 * @param	loc		ubicacion en memoria
	 * @return	declaracion de una variable
	 */
	public static String var(String name, String type, String scope, int loc) {
		
		return name + ", " + type + ", " + scope + ", " + loc + " #";
	}
	
	/*
	 * Regresa la ubicacion actual de instruccion en el codigo.
	 * 
	 * @return	ubicacion actual de instruccion
	 */
	public static int emitLoc() {
		
		return emitLoc;
	}
}
